using System;

namespace Bookvar.ObjectModel.Actions
{
    /// <summary>
    /// A base class for all actions working with the <see cref="Bookvar.ObjectModel.Topic"/> class.
    /// </summary>
    public abstract class TopicActionBase : ActionBase
    {
        private Topic topic;

        /// <summary>
        /// Gets or sets the target topic for this action.
        /// </summary>
        /// <remarks>
        /// This is a mandatory property for this action.
        /// </remarks>
        /// <value>The topic.</value>
        /// <exception cref="ArgumentNullException">if value is null.</exception>
        public Topic Topic
        {
            get { return topic; }
            set
            {
                if(value == null) throw new ArgumentNullException("value");

                topic = value;
                OnTopicChanged();
            }
        }

        /// <summary>
        /// Called when the <see cref="Topic"/> is changed.
        /// </summary>
        protected virtual void OnTopicChanged()
        {
        }

        /// <summary>
        /// Executes (or redoes) the logic for the action.
        /// </summary>
        /// <exception cref="InvalidOperationException">if the topic for this action is not set;
        /// or if the execute method is called twice with no Undo between the calls.</exception>
        public override void Execute()
        {
            base.Execute();

            if ( topic == null )
            {
                // TODO: move to SR
                throw new InvalidOperationException( "Could not execute the action without a target topic." );
            }
        }

        /// <summary>
        /// Undoes the action.
        /// </summary>
        /// <exception cref="InvalidOperationException">if the topic for this action is not set; 
        /// or if Undo is called before the action is executed. </exception>
        public override void Undo()
        {
            base.Undo();

            if ( topic == null )
            {
                // TODO: move to SR
                throw new InvalidOperationException( "Could not undo the action without a target topic." );
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="TopicActionBase"/> class.
        /// </summary>
        protected TopicActionBase()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="TopicActionBase"/> class.
        /// </summary>
        /// <param name="topic">The topic.</param>
        /// <exception cref="ArgumentNullException">if <paramref name="topic"/>is null.</exception>
        protected TopicActionBase( Topic topic )
        {
            if ( topic == null ) throw new ArgumentNullException( "topic" );

            this.topic = topic;
        }
    }
}
